home *** CD-ROM | disk | FTP | other *** search
/ Aminet 2 / Aminet AMIGA CDROM (1994)(Walnut Creek)[Feb 1994][W.O. 44790-1].iso / Aminet / misc / amag / sh9301e.lha / Maxon-CPP-Demo / Source / FPlot / fclass.c next >
C/C++ Source or Header  |  1993-02-17  |  9KB  |  449 lines

  1. /*
  2.   Funktionsplotter in Maxon C++
  3.  
  4.   Function-Modul
  5.  
  6.   Jens Gelhar 09.11.91
  7. */
  8.  
  9.  
  10. #include <exec/types.h>
  11. #include <intuition/intuition.h>
  12.  
  13. #include <stream.h>
  14. #include <stdio.h>
  15. #include <math.h>
  16. #include <stdlib.h>
  17. #include <ctype.h>
  18.  
  19. #include "fclass.h"
  20.  
  21. // ******** Prototypen ********
  22.  
  23. struct Window *OpenWindow( struct NewWindow *newWindow );
  24. void CloseWindow( struct Window *window );
  25.  
  26. void SetAPen( struct RastPort *rp, unsigned long pen );
  27. void Move( struct RastPort *rp, long x, long y );
  28. void Draw( struct RastPort *rp, long x, long y );
  29.  
  30. struct Message *WaitPort( struct MsgPort *port );
  31.  
  32. // ******** Pragmas ***********
  33.  
  34. #pragma amicall(SysBase, 384, WaitPort(a0))
  35.  
  36. #pragma amicall(GfxBase, 240, Move(a1,d0,d1))
  37. #pragma amicall(GfxBase, 246, Draw(a1,d0,d1))
  38. #pragma amicall(GfxBase, 342, SetAPen(a1,d0))
  39.  
  40. #pragma amicall(IntuitionBase, 204, OpenWindow(a0))
  41. #pragma amicall(IntuitionBase, 72, CloseWindow(a0))
  42.  
  43. // ******** Zeichenroutine ********
  44.  
  45. // Windowdimensionen:
  46. #define WW 640
  47. #define WH 190
  48.  
  49.  
  50. // Destruktoren:
  51.  
  52. Func::~Func() { }       // Default: garnix
  53.  
  54. UnOpN::~UnOpN()
  55.  { delete arg; }
  56.  
  57. BinOpN::~BinOpN()
  58.  { delete l;
  59.    delete r;
  60.  }
  61.  
  62. // Konstruktoren:
  63.  
  64. double Func::Dummy;
  65.  
  66. KonstN::KonstN (double c)
  67.  { Konst = c; }
  68.  
  69. UnOpN::UnOpN(UnOps op, Func *n):
  70.  oper(op), arg(n)
  71. { }
  72.  
  73. BinOpN::BinOpN(BinOps op, Func *ln, Func *rn):
  74.  oper(op), l(ln), r(rn)
  75. { }
  76.  
  77. // "Konstant"-Funktionen:
  78.  
  79. int Func::isconst (double &retval)
  80.   { return 0; }
  81.  
  82. int KonstN::isconst (double &retval)
  83.   { retval = Konst;
  84.     return 1;
  85.   }
  86.  
  87. // Ausgabe
  88.  
  89. #define EPANIC 26731
  90.  
  91. void KonstN::print(char*)
  92.  {
  93.    printf("%g", Konst);
  94.  }
  95.  
  96. void VarN::print(char*)
  97.  { printf("x"); }
  98.  
  99. void ErrorN::print(char*)
  100.  { printf("?"); }
  101.  
  102. void UnOpN::print(char* str)
  103.   { switch(oper)
  104.     { case Op_neg: printf("-"); break;
  105.       case Op_sqr: printf("sqr "); break;
  106.       case Op_sqrt: printf("sqrt "); break;
  107.       case Op_sin: printf("sin "); break;
  108.       case Op_cos: printf("cos "); break;
  109.       case Op_exp: printf("exp "); break;
  110.       case Op_ln:  printf("ln "); break;
  111.     }
  112.     arg->print(str);
  113.   }
  114.  
  115. void BinOpN::print(char* str)
  116.   { printf("(");
  117.     l->print(str);
  118.     switch (oper)
  119.     { case Op_add: printf("+"); break;
  120.       case Op_sub: printf("-"); break;
  121.       case Op_mult:printf("*"); break;
  122.       case Op_div: printf("/"); break;
  123.       case Op_pot: printf("^"); break;
  124.       default: exit(EPANIC);
  125.     }
  126.     r->print(str);
  127.     printf(")");
  128.   }
  129.  
  130. // Auswertung
  131.  
  132. inline double sqr(double x)
  133.   { return x*x; }
  134.  
  135. double intpotz(double base, int exp)
  136.   { if (exp)
  137.       { if (exp<0) return 1.0/intpotz(base,-exp)
  138.         else if (exp==1) return base;
  139.         else if (exp&1) return base*sqr(intpotz(base, exp/2));
  140.                         else return sqr(intpotz(base, exp/2));
  141.        }
  142.      else return 1;
  143.   }
  144.  
  145. double UnOpN::eval (double x)
  146.  {
  147.    double y = arg->eval(x);
  148.  
  149.    switch(oper)
  150.    { case Op_neg:  return -y;
  151.      case Op_sqr:  return y*y;
  152.      case Op_sqrt: return sqrt(y);
  153.      case Op_sin:  return sin(y);
  154.      case Op_cos:  return cos(y);
  155.      case Op_exp:  return exp(y);
  156.      case Op_ln:   return log(y);
  157.      default: exit(EPANIC);
  158.    }
  159. }
  160.  
  161. double BinOpN::eval (double x)
  162.  { double lv = l->eval(x), rv = r->eval(x);
  163.    switch(oper)
  164.    { case Op_add:  return lv+rv;
  165.      case Op_sub:  return lv-rv;
  166.      case Op_mult: return lv*rv;
  167.      case Op_div:  return lv/rv;
  168.      case Op_pot:  if (r->isconst() && floor(rv)==rv)
  169.                      return intpotz(lv, int(rv))
  170.                    else if (lv > 0) return exp(rv*log(lv));
  171.                                     return 0;
  172.      default: exit(EPANIC);
  173.    }
  174.  }
  175.  
  176.  
  177. // ******** Parsing ********
  178.  
  179. #define EULER 2.7182818284
  180. #define PI 3.141592653589
  181.  
  182. char *cp;       // Zeiger auf String
  183. char c;         // gescanntes Zeichen
  184. short ErrFlag;  // Fehler aufgetreten?
  185.  
  186.  
  187. char Get()
  188. { while ((c = *cp) == ' ')
  189.     cp++;
  190.   if(c) cp++;
  191.   return c;
  192. }
  193.  
  194. Func *Fehler()
  195.  { if (!ErrFlag)
  196.      { cout << "\nError.\n";
  197.        ErrFlag = 1;
  198.      }
  199.    return new ErrorN;
  200.  }
  201.  
  202. Func *Expression();
  203.  
  204. Func *Term();
  205.  
  206. Func *Potenz();
  207.  
  208. Func *Factor()
  209. { while (c=='+') Get();
  210.  
  211.   if (c=='x' || c=='X')
  212.     { Get();
  213.       return new VarN;
  214.     }
  215.   else if (c >= '0' && c <= '9')
  216.     {
  217.       int i = 0;
  218.       enum {max = 80};
  219.       char numstr[max+1];
  220.  
  221.       while (isdigit(c) && i<max)
  222.         { numstr[i++] = c; Get(); }
  223.  
  224.       if (c=='.')
  225.         { numstr[i++] = c; Get(); }
  226.       while (isdigit(c) && i<max)
  227.         { numstr[i++] = c; Get(); }
  228.  
  229.       if (tolower(c)=='e')
  230.         { numstr[i++] = c; Get();
  231.  
  232.           if (c=='+' || c=='-')
  233.             { numstr[i++] = c; Get(); }
  234.           else
  235.           if (!isdigit(c))
  236.             return Fehler();
  237.  
  238.           while (isdigit(c) && i<max)
  239.             { numstr[i++] = c; Get(); }
  240.  
  241.         }
  242.  
  243.       numstr[i]=0;
  244.       return new KonstN(atof(numstr));
  245.      }
  246.    else
  247.    if (c=='(')
  248.      { Get();
  249.        Func *np = Expression();
  250.        if (c==')')
  251.          Get();
  252.        else
  253.          delete Fehler();
  254.        return np;
  255.      }
  256.    else
  257.    if (c=='c')
  258.      { if (Get()=='o' && Get() == 's')
  259.          { Get(); return new UnOpN(Op_cos, Factor()); }
  260.        else
  261.          return Fehler();
  262.      }
  263.    else
  264.    if (c=='e')
  265.      { if (Get()!='x')
  266.          return new KonstN(EULER);
  267.        else if (Get() == 'p')
  268.          { Get(); return new UnOpN(Op_exp, Factor()); }
  269.        else
  270.          return Fehler();
  271.      }
  272.    else if (c=='l')
  273.      { if (Get()=='n')
  274.          return Get(), new UnOpN(Op_ln, Factor());
  275.        else
  276.          return Fehler();
  277.      }
  278.    else if (c=='p')
  279.      { if (Get()!='i')
  280.          return Fehler();
  281.        Get(); return new KonstN(PI);
  282.      }
  283.    else if (c=='s')
  284.      { Get();
  285.        if (c=='i')
  286.          { if (Get() != 'n') return Fehler();
  287.            Get();
  288.            return new UnOpN(Op_sin, Factor());
  289.          }
  290.        else if (c=='q')
  291.          { if (Get() != 'r') return Fehler();
  292.            if (Get()=='t')
  293.              { Get();
  294.                return new UnOpN(Op_sqrt, Factor());
  295.              }
  296.            else return new UnOpN(Op_sqr, Factor());
  297.          }
  298.        else
  299.          return Fehler();
  300.      }
  301.  
  302.    // Default-Ergebnis:
  303.    return Fehler();
  304. }
  305.  
  306. Func *Potenz()
  307. {
  308.   Func *n1 = Factor();
  309.  
  310.   while (c=='^')
  311.     { Get();
  312.       Func *n2 = Factor();
  313.       n1 = new BinOpN(Op_pot, n1, n2);
  314.     }
  315.   return n1;
  316. }
  317.  
  318. Func *Term()
  319. { Func *n1 = Potenz();
  320.  
  321.   while (c=='*' || c=='/')
  322.     { BinOps op = c=='*'? Op_mult : Op_div;
  323.       Get();
  324.       Func *n2 = Potenz();
  325.       n1 = new BinOpN(op, n1, n2);
  326.     }
  327.   return n1;
  328. }
  329.  
  330. Func *Expression()
  331. {
  332.   if (c=='-')
  333.    { Get();
  334.      Func *np = Term();
  335.        return new UnOpN(Op_neg,np);
  336.    }
  337.   else
  338.    { Func *n1 = Term();
  339.      while (c=='+' || c=='-')
  340.        { BinOps op = c=='+'? Op_add : Op_sub;
  341.          Get();
  342.          Func *n2 = Term();
  343.          n1 = new BinOpN(op, n1, n2);
  344.        }
  345.      return n1;
  346.    }
  347. }
  348.  
  349. Func *Parse(char *string)
  350. { cp = string;
  351.   ErrFlag = 0;
  352.  
  353.   Get();
  354.   Func *expr = Expression();
  355.   if (c) delete Fehler();
  356.  
  357.   if(ErrFlag)
  358.     { delete expr; return 0; }
  359.   else
  360.     return expr;
  361. }
  362.  
  363. #pragma break -
  364.  
  365. void plot(Func *f, double minx, double maxx, double miny, double maxy)
  366. {
  367.   NewWindow mynewwin =
  368.    { 0, 0, WW, WH+10, 2, 1, IDCMP_CLOSEWINDOW,
  369.      WFLG_ACTIVATE | WFLG_SIZEGADGET | WFLG_DRAGBAR | WFLG_DEPTHGADGET | WFLG_CLOSEGADGET | WFLG_GIMMEZEROZERO,
  370.      NULL, NULL, " Plot ++ ", NULL, NULL, 100, 50, 640, 200, WBENCHSCREEN};
  371.  
  372.   struct Window* mywin = OpenWindow( &mynewwin);
  373.   if (!mywin) exit(1);
  374.  
  375.   RastPort *RP = ( RastPort *)mywin->RPort;
  376.  
  377.   double XS = WW / (maxx-minx), YS = WH / (maxy-miny);
  378.  
  379.   int X0 = int(-XS*minx), Y0 = int(-YS*miny);
  380.  
  381.   SetAPen( ( RastPort *)mywin->RPort, 3);
  382.   if (miny < 0 && maxy > 0)
  383.     { // y-Achse zeichnen:
  384.       Move(RP,  0, WH-Y0);
  385.       Draw(RP, WW, WH-Y0);
  386.     }
  387.  
  388.   if (minx < 0 && maxx > 0)
  389.     { // x-Achse zeichnen:
  390.       Move(RP, X0, 0);
  391.       Draw(RP, X0, WH);
  392.     }
  393.  
  394.   SetAPen( ( RastPort *)mywin->RPort, 0);
  395.   Move( ( RastPort *)mywin->RPort, 0, 0);
  396.  
  397.   for (int i=0; i<WW; i++)
  398.     { double x = minx+i/XS, y = f->eval(x);
  399.       int yp = int(YS*y+Y0);
  400.  
  401.       if (yp > -WH && yp < 2*WH) Draw(RP, i, WH-yp);
  402.       SetAPen(RP, 1);
  403.     }
  404.  
  405.   WaitPort(mywin->UserPort);
  406.   CloseWindow(mywin);
  407. }
  408.  
  409. #pragma break +
  410.  
  411. void main()
  412. {
  413.   char input[100], buf[200];
  414.  
  415.   cout << "\nPlot ++\nGeschrieben von Jens Gelhar mit Maxon C++\n\n";
  416.  
  417.   cout << "Funktion: f(x) = "; cin.getline(input, 100);
  418.  
  419.   Func *MyExp = Parse(input);
  420.  
  421.   if (MyExp)
  422.     { double minX, maxX, minY, maxY;
  423.  
  424.       for(;;)
  425.        { cout << "X-Bereich: von "; cin >> minX;
  426.          cout << "           bis "; cin >> maxX;
  427.          if (minX < maxX) break;
  428.          cout << "Das Minimum muß kleiner als das Maximum sein.\n";
  429.        }
  430.  
  431.       for(;;)
  432.        { cout << "Y-Bereich: von "; cin >> minY;
  433.          cout << "           bis "; cin >> maxY;
  434.          if (minY < maxY) break;
  435.          cout << "Das Minimum muß kleiner als das Maximum sein.\n";
  436.        }
  437.  
  438.       cout << "\nFunktion: "; MyExp->print(buf); cout << "\n";
  439.  
  440.       plot(MyExp, minX, maxX, minY, maxY);
  441.  
  442.       delete MyExp;
  443.     }
  444.   else
  445.     cout << "Versuch's doch gleich noch mal!\n";
  446.  
  447. }
  448.  
  449.